package SpringBoot.spring_boot_starter_security.D03_权限校验.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry;
import org.springframework.security.core.userdetails.UserDetailsService;

import com.titan.core.utils.spring.SpringUtils;

/**
 *
 *
 * @author 周成功
 *
 */
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    // 自定义的认证方式
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 指定密码加密所使用的加密器为passwordEncoder()  
        // 需要将密码加密后写入数据库
        UserDetailsService service = SpringUtils.getBean(UserDetailsService.class);
//        auth.userDetailsService(service).passwordEncoder(passwordEncoder());  
//        auth.eraseCredentials(false);
        auth.userDetailsService(service);
    }

    
    /**
     * .anyRequest().authenticated()    // 表示其他的请求都必须要有权限认证。
     * .permitAll                       // 表示该请求任何人都可以访问
     * 通过匹配器来匹配路径，比如antMatchers方法
     *    假设我要管理员才可以访问admin文件夹下的内容，我可以这样来写：.antMatchers("/admin/**").hasRole("ROLE_ADMIN")
     *    设置admin文件夹下的文件可以有多个角色来访问，写法如下：.antMatchers("/admin/**").hasAnyRole("ROLE_ADMIN","ROLE_USER") 
     * 通过hasIpAddress来指定某一个ip可以访问该资源
     *    假设只允许访问ip为210.210.210.210的请求获取admin下的资源，写法如下.antMatchers("/admin/**").hasIpAddress("210.210.210.210") 
     * 
     * 更多的权限控制方式参看如下
     *    方法名                                                               用途
     *    access(String)                Spring EL表达式结果为true时可访问
     *    anonymous()                   匿名可访问
     *    denyAll()                     用户不可以访问
     *    fullyAuthenticated()          用户完全认证可访问（非remember me下自动登录）
     *    hasAnyAuthority(String...)    参数中任意权限的用户可访问
     *    hasAnyRole(String...)         参数中任意角色的用户可访问
     *    hasAuthority(String)          某一角色的用户可访问
     *    hasRole(String)               某一角色的用户可访问
     *    permitAll()                   所有用户可访问
     *    rememberMe()                  允许通过remember me登录的用户访问
     *    authenticated()               用户登录后可访问
     *    hasIpAddress(String)          用户来自参数中的ip时可访问
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 注册所有用户均可访问的资源
        http.authorizeRequests().antMatchers("/**/index.css*", "/**/index.js*", "/**/favicon.ico*", "/webjars/**").permitAll();

        // 注册登录页面
        http.authorizeRequests().and()
                .formLogin().loginPage("/login")
                .failureUrl("/login?error")
                .permitAll();
        
        // 注册注销页面
        http.authorizeRequests().and().logout()
//        .logoutSuccessUrl("/home") //退出登录后的默认网址是”/home” 
                .permitAll();
//        .successHandler(loginSuccessHandler()) //登录成功后可使用loginSuccessHandler()存储用户信息，可选。
//        .invalidateHttpSession(true)
        
        // 所有的请求需要认证即登陆后才能访问
        http.authorizeRequests().anyRequest().authenticated();
        
        // 登录后记住用户，下次自动登录,数据库中必须存在名为persistent_logins的表  
//      .rememberMe()
//          .tokenValiditySeconds(1209600);        

        
        // 禁用csrf          
        http.csrf().disable();
    }
    
    
    

//    
//    @Bean  
//    public BCryptPasswordEncoder passwordEncoder() {  
//        return new BCryptPasswordEncoder(4);  
//    }  
//  
//    @Bean  
//    public LoginSuccessHandler loginSuccessHandler(){  
//        return new LoginSuccessHandler();  
//    }    
    
}
